package com.lfs.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.lfs.base.exception.BusinessException;
import com.lfs.base.util.CollectionUtils;
import com.lfs.base.util.MD5NewUtils;
import com.lfs.common.cache.redis.base.MapCache;
import com.lfs.common.cache.redis.base.StringCache;
import com.lfs.common.constant.CommonConstants;
import com.lfs.common.constant.Constant;
import com.lfs.common.utils.StringUtils;
import com.lfs.dao.ApiChargeDao;
import com.lfs.interfaces.agent.service.AgentSerivce;
import com.lfs.interfaces.bank.service.BankService;
import com.lfs.interfaces.dto.ResultReturn;
import com.lfs.interfaces.model.ApiOrderNotify;
import com.lfs.interfaces.model.BankInfo;
import com.lfs.interfaces.model.dto.ChargeDto;
import com.lfs.interfaces.model.dto.OrderDto;
import com.lfs.interfaces.model.vo.AgentVo;
import com.lfs.interfaces.model.vo.ChargeVo;
import com.lfs.interfaces.model.vo.ProductVo;
import com.lfs.interfaces.order.service.OrderBaseService;
import com.lfs.interfaces.product.service.ProductService;
import com.lfs.service.ApiChargeSerivce;
import com.lfs.util.GetOrderUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageBuilder;
import org.springframework.amqp.core.MessageDeliveryMode;
import org.springframework.amqp.core.MessageProperties;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.AbstractJavaTypeMapper;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.List;


@Service
public class ApiChargeServiceImpl implements ApiChargeSerivce {

    private Logger logger = LoggerFactory.getLogger(ApiChargeServiceImpl.class);

    @Value("${bc.serverIp}")
    private String serverIp;

    @Value("${bc.secretKey}")
    private String secretKey;

    @Value("${order_charge_rabbitmq_exchange}")
    private String orderChargeExchange;

    @Resource
    private ApiChargeDao chargeDao;

    @Autowired
    private BankService bankService;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Resource
    private OrderBaseService orderBaseService;

    @Resource
    private ProductService productService;

    @Resource
    private AgentSerivce agentSerivce;

    @Autowired
    private ObjectMapper objectMapper;

    @Autowired
    private MapCache mapCache;

    @Autowired
    private StringCache stringCache;

    @Override
    public ResultReturn<ChargeVo> charge(ChargeDto chargeDto) {
        ResultReturn<ChargeVo> resultReturn = new ResultReturn<>();
        resultReturn.setStatus(CommonConstants.RESP_CHARGE_HANDLE).setMsg("订单正在处理中");
        ChargeVo vo = new ChargeVo();
        vo.setReqStreamId(chargeDto.getReqStreamId());
        vo.setApplyTime(Constant.getDateTime());
        String chargeType = chargeDto.getChargeType();
        ApiOrderNotify apiOrderNotify = new ApiOrderNotify();
        apiOrderNotify.setAgtPhone(chargeDto.getAgtPhone());
        apiOrderNotify.setReqStreamId(chargeDto.getReqStreamId());
        apiOrderNotify.setNotifyUrl(chargeDto.getNotifyUrl());
        apiOrderNotify.setChargeMoney(chargeDto.getChargeMoney());

        try {
            if (null != chargeDto.getProductCode() && !"".equals(chargeDto.getProductCode())) {
                // 校验产品信息
                long startR = System.currentTimeMillis();
                chargeDto.setChargeType(CommonConstants.BANK_CARD_TYPE);
                ResultReturn<ProductVo> resultProduct = productService.verifyOrder(chargeDto);
                logger.info("----------检验产品信息消耗时间-------------" + (System.currentTimeMillis() - startR));
                if (resultProduct.getStatus().equals(CommonConstants.RESP_CHARGE_SUCCESS)) {
                    // 数据校验成功，提交充值
                    ProductVo product = resultProduct.getData();
                    logger.info("请求流水号[" + chargeDto.getReqStreamId() + "]选择供应商[" + product.getUpChannel() + "]");
                    OrderDto orderDto = new OrderDto();
                    orderDto.setOrderNo(GetOrderUtil.getOrderNo(serverIp));
                    if(product.getPrice().compareTo(new BigDecimal(0.00)) == 0){
                        orderDto.setOutMoney(chargeDto.getChargeMoney().multiply(product.getDiscount()));
                        orderDto.setPrice(chargeDto.getChargeMoney());
                    }else{
                        orderDto.setOutMoney(product.getPrice().multiply(product.getDiscount()));
                        orderDto.setPrice(product.getPrice());
                    }
                    orderDto.setDownOrderNo(chargeDto.getReqStreamId());
                    orderDto.setAgtPhone(chargeDto.getAgtPhone());
                    orderDto.setAccountIp(chargeDto.getAccountIp());
                    orderDto.setChargeAddr(chargeDto.getChargeAddr());
                    orderDto.setChargeMoney(chargeDto.getChargeMoney());
                    orderDto.setProfit(product.getDiscount());
                    orderDto.setBusinessCode(product.getBusinessCode());
                    orderDto.setProductCode(product.getProductCode());
                    orderDto.setRechargeType("");
                    orderDto.setArriveType(product.getArriveType());
                    orderDto.setState(CommonConstants.DEFAULT);
                    orderDto.setStockState(CommonConstants.DEFAULT);
                    orderDto.setProductType(product.getProductType());
                    orderDto.setChargeType(chargeType);
                    orderDto.setExp2(chargeDto.getExp());
                    long start = System.currentTimeMillis();
                    ResultReturn<Long> resultInfo = orderBaseService.createOrder(orderDto);
                    Long orderId = resultInfo.getData();
                    logger.info("【createOrder所需时间】" + (System.currentTimeMillis() - start));
                    orderDto.setId(orderId);
                    vo.setOrderNo(orderDto.getOrderNo());
                    vo.setBalance(orderDto.getChargeMoney());
                    vo.setAgtPhone(orderDto.getAgtPhone());
                    if (orderId > 0) {
                        apiOrderNotify.setOrderNo(orderDto.getOrderNo());
                        // 订单插入回调表
                        if (StringUtils.isNotBlank(apiOrderNotify.getNotifyUrl())) {
                            insertOrderNotify(apiOrderNotify);
                        }
                        // 发送充值请求到消息队列
                        long startMq = System.currentTimeMillis();
                        if(CommonConstants.ALIPAY_TYPE.equals(orderDto.getChargeType())){
                            rabbitTemplate.setMessageConverter(new Jackson2JsonMessageConverter());
                            rabbitTemplate.setExchange(orderChargeExchange);
                            Message message= MessageBuilder.withBody(objectMapper.writeValueAsBytes(orderDto)).setDeliveryMode(MessageDeliveryMode.PERSISTENT).build();
                            message.getMessageProperties().setHeader(AbstractJavaTypeMapper.DEFAULT_CONTENT_CLASSID_FIELD_NAME, MessageProperties.CONTENT_TYPE_JSON);
                            rabbitTemplate.convertAndSend(message);
                        }
                        resultReturn.setStatus(CommonConstants.RESP_CHARGE_HANDLE).setData(vo)
                                .setMsg("充值提交成功");
                        logger.info("----------操作mq所用时间----------" + (System.currentTimeMillis() - startMq));
                    } else {
                        resultReturn.setStatus(CommonConstants.RESP_CHARGE_FAIL).setData(vo).setMsg("充值提交失败|"+resultInfo.getMsg());
                    }
                    if (resultReturn.getStatus().equals(CommonConstants.RESP_CHARGE_VALIDBUSINESS)) {
                        // 通道不存在，改为失败
                        orderDto.setErrorCode(CommonConstants.RESP_CHARGE_VALIDBUSINESS + "|" + "充值提交失败");
                        orderDto.setRemark("提交上游失败");
                        orderDto.setState(CommonConstants.FAIL);
                        orderDto.setAccountBalance(new BigDecimal(0));
                        orderDto.setUpOrderNo("");
                        orderDto.setCheckState(CommonConstants.FAIL);
                        orderBaseService.updateOrderAfterCharge(orderDto);
                    }
                } else {
                    resultReturn.setStatus(resultProduct.getStatus()).setData(vo).setMsg(resultProduct.getMsg());
                }
            }
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            resultReturn.setStatus(CommonConstants.RESP_CHARGE_EXCETION).setData(vo).setMsg("提交订单异常");
        }
        return resultReturn;
    }

    public int insertOrderNotify(ApiOrderNotify apiOrderNotify) {
        try {
            if (chargeDao.insertOrderNotify(apiOrderNotify) > 0) {
                return 1;
            } else {
                return 0;
            }
        } catch (Exception e) {
            return 0;
        }
    }
}
